#ifndef _Image_H_
#define _Image_H_
#include "Matrix.h"
#include <QImage>

enum Channel {RED , GREEN , BLUE};

class Image : public Matrix
{
public:

    Image();  // 构造函数，创建行列都为零的Image对象
    Image(int h, int w);// 构造函数重载，创建h行，w列的Image对象;
    Image(int h, int w, Pixel pix);// 构造函数重载，创建的图像像素值都为val;
    Image(const char* ImageName); // 构造函数重载，利用文件名从硬盘加载图像文件成为Image对象;
    Image(const Matrix &m); //构造函数重载，由Matrix类对象构造Image类对象
    Image(const Image &im); //拷贝构造函数;
    virtual ~Image(); //析构函数;

    //从硬盘文件中读入图像数据;
    //返回值：1 文件打开失败；2 文件格式不符
    int ReadBMP(const char* ImageName);

    //将图像数据保存为图像文件;
    //返回值：1 文件打开失败
    int WriteBMP(const char* filename);

    void Flip(int code); //图像的翻转; code为0左右，1 上下;
    void Resize(int h, int w); //图像的缩放为参数指定的大小
    int remHaze(int minwinSize  = 3,int tranwinSize = 3, double tran = 0.1, double w = 0.95);//去雾
    void brightAdj(double mul);//图片亮度调整
    // 灰度化
    void gray();

    // 伽马变换
    void gamma();

    // 用于消除valid卷积对图片边界的影响
    void fix(int sizeKernel);

    // 高斯滤波
    void Gaussian_filter(int flage = 0);

    // 均值滤波
    void mean_filter();

    // 中值滤波
    void mid_value_filter();

    // 高斯金字塔->缩小
    void lower();

    // 高斯金字塔->放大
    void upper();

    // 阈值处理 默认内部会先转换成灰度图
    void threshold(int thresh = 127, int maxval = 255, int type = 0);

    // 图像梯度 Sobel算子
    void Sobel();

    // 边缘检测
    void Canny(int minVale = 70, int maxVale = 110);

    // 图像马赛克化
    void Mosaic();

    //裁剪点(x1,y1)到点(x2,y2)的图像
    //返回值：1 输入值不合理
    int Cut(int x1,int y1,int x2,int y2);

    //图像旋转的函数（旋转角度为90度的整数倍）
    //返回值：1 输入值不合要求（不是90的倍数）
    int Rotate(int degree);

    unsigned char * getData();//获得图像数据（转QImage）
    unsigned char & getChannel(int height , int width , int color);//获得对应通道， color为通道
    void setChannel(int height , int width , int color, unsigned char cha);//设置通道值
    void minFilter(int winSize = 3);//最小值滤波

    int height()//获得图像高
    {
        return Height();
    }
    int width()//获得图像宽
    {
        return Width();
    }
    Pixel & pixel(int height, int width)//获得对应位置像素
    {
        return At(height,width);
    }
    void setPixel(int height, int width, Pixel pix)//设置像素值
    {
        At(height, width) = pix;
    }
    void setPixel(int height,int width,unsigned char red,unsigned char gre, unsigned char blu)
    {
        setPixel(height,width,{red, gre, blu});
    }

    operator QImage()//类型转换函数
    {
        return QImage(getData(),Width(),Height(),QImage::Format_RGB888);
    }

    Image& operator=(const Image & img);//图像拷贝
    //通道自增
    Image& operator++();
    Image operator++(int);

    //通道自减
    Image& operator--();
    Image operator--(int);
private:
    unsigned char * dataI = nullptr;
};
typedef Image MyQImage;
#endif
